package com.whately.core.base.fileupload.qiniu.model;

import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import com.whately.core.base.exception.ServiceException;
import com.whately.core.base.fileupload.constant.FileModeEnum;
import com.whately.core.base.fileupload.constant.FileSenderTypeEnum;
import com.whately.core.base.fileupload.qiniu.util.ImageInfoVo;
import com.whately.core.base.fileupload.vo.FileSenderBO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class QiNiuStorageUtil {

    /**
     * 定义七牛服务器存储的区域
     * 华东zone0()、华北zone1()、华南zone2()、北美zoneNa0()
     *
     *
     */
    public static final Zone ZONE_AREA = Zone.zone1();
    private static final Configuration cfg = new Configuration(ZONE_AREA);


    //设置好账号的ACCESS_KEY和SECRET_KEY
    public static String ACCESS_KEY ;
    public static String SECRET_KEY  ;

    // 用于七牛云上传的bucket
    private static Map<String, String> qiNiuBucketList;


    @Autowired
    private QiNiuBean qiNiuBean;

    private static Auth auth;

    @PostConstruct
    public void init() {
        // 临时的bean引用 赋给 static 属性
        ACCESS_KEY = qiNiuBean.getAccessKey();
        SECRET_KEY = qiNiuBean.getSecretKey();

        qiNiuBucketList = new HashMap<>();
        qiNiuBucketList.put(FileModeEnum.img_opened.getMode(), qiNiuBean.getImgOpenedBucket());
        //私有空间
        qiNiuBucketList.put(FileModeEnum.img_private.getMode(), qiNiuBean.getImgPrivateBucket());

        auth = Auth.create(ACCESS_KEY, SECRET_KEY);
    }



    /**
     * 上传视频
     *  并指定解码
     * fileName 格式：/yyyy/mm/dd/nameHash.mp4
     */
    public static ImageInfoVo uploadVideo(String bucket, ImageInfoVo imageInfoVo, FileSenderBO fileSenderBO) {
        QiNiuModel model = geneQiNiuBucketInfo(bucket,imageInfoVo);
        String uploadToken = getToken4Video(model.getQiNiuBucket(),model.getKey());
        return uploadFileOrByteData(uploadToken,model,imageInfoVo,fileSenderBO);
    }




    /**
     * 上传图片
     * @param bucket
     * @param imageInfoVo
     * @return
     */
    public static ImageInfoVo uploadFile(String bucket, ImageInfoVo imageInfoVo, FileSenderBO fileSenderBO) {
        QiNiuModel model = geneQiNiuBucketInfo(bucket,imageInfoVo);
        String uploadToken = getToken4CommonFile(model.getQiNiuBucket(),model.getKey());
        return uploadFileOrByteData(uploadToken,model,imageInfoVo,fileSenderBO);
    }


    private static QiNiuModel geneQiNiuBucketInfo(String bucket,ImageInfoVo imageInfoVo){
        QiNiuModel model = new QiNiuModel();

        String fileName = imageInfoVo.qiNiuDateFilePathAndName();
        String fileMode = fileName.substring(15, 17);
        String qiNiuBucket = qiNiuBucketList.get(fileMode);
        String key = bucket+imageInfoVo.getPrefixBeforeDatePath()+imageInfoVo.getRelativePathAndFileName();

        model.setQiNiuBucket(qiNiuBucket);
        model.setKey(key);
        return model;
    }

    private static ImageInfoVo uploadFileOrByteData(String uploadToken,QiNiuModel model, ImageInfoVo imageInfoVo,FileSenderBO fileSenderBO) {
        Object content = fileSenderBO.getContent();
        FileSenderTypeEnum type = fileSenderBO.getFileSenderTypeEnum();
        UploadManager uploadManager = new UploadManager(cfg);

        // 这里不需要检查,调用者保证
        String key = model.getKey();
        Response response =null;
        try {
            switch (type){
                case bytes_array:
                    response = uploadManager.put((byte[])content, key, uploadToken);
                    break;
                case file:
                    response = uploadManager.put((File)content, key, uploadToken);
                    break;
                case input_stream:
                    response = uploadManager.put((InputStream) content, key, uploadToken,null,null);
                    break;
            }
        } catch (QiniuException e) {
            log.error("upload file to qiniu fail,type {} , upload to {}, error:{}", type, key, e);

            throw new ServiceException(400,"上传文件服务器异常");
        }

        if (response!=null&&response.isOK()) {
            log.info("upload to qiniu success, file name:{}", key);
        } else {
            // 失败即抛出异常
            log.error("upload to qiniu fail，type {} , upload to {}, error:{}", type, key, response);
            throw new ServiceException(400,"上传文件服务器异常"+ response==null?"":response.error);
        }
        // 生成完整可用的URL
        return imageInfoVo;
    }

    /************************************
     *  token  普通文件和视频文件有区别
     ***********************************/

    //key 上传指定文件，强制覆盖
    private static String getToken4CommonFile(String qiuNiuBucket,String key) {
        String token = auth.uploadToken(qiuNiuBucket,key);
        return token;
    }

    private static String getToken4Video(String qiuNiuBucket,String key) {
        //默认不指定key的情况下,以文件内容的hash值作为文件名
        //String key = "1234567";

        //密钥配置
        //1.进行身份认证
        //设置转码操作参数
        String fops = "avthumb/mp4/vcodec/libx264";
        //可以对转码后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
        //转码后的文件，覆盖原文件
        String urlbase64 = UrlSafeBase64.encodeToString(qiuNiuBucket + ":" + key );

        String pfops = fops + "|saveas/" + urlbase64;
        String upToken = auth.uploadToken(qiuNiuBucket, null, 3600, new StringMap().putNotEmpty("persistentOps", pfops));

        return upToken;
    }



    /************************************
     *  七牛私有bucket的url，默认 3600秒有效时间
     ***********************************/

    public static  String signPrivateUrl(String imgUrl){
        String downloadUrl = auth.privateDownloadUrl(imgUrl);
        return downloadUrl;
    }


    //private static String getToken4CommonFileAndGenerateZoom(String qiuNiuBucket,String key,ImageInfoVo imageInfoVo) {
      //  return getToken4CommonFile(qiuNiuBucket,key);

        //异步转码，并且持久化
        /*
        //密钥配置
        //1.进行身份认证
        ImageBucketEnum bucketEnum = ImageBucketEnum.getByValue(imageInfoVo.getBucket());
        if(bucketEnum.getHeight()==null||bucketEnum.getWidth()==null){
            return getToken4CommonFile(qiuNiuBucket,key);
        }
        //设置转码操作参数
        String fops = "imageView2/2/w/"+bucketEnum.getWidth()+"/h/"+bucketEnum.getHeight();
        //可以对转码后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
        //转码后的文件，覆盖原文件
        int index=key.indexOf(".");
        String slimKey = key.substring(0,index)+"-zoom"+key.substring(index);
        String urlbase64 = UrlSafeBase64.encodeToString(qiuNiuBucket + ":" + slimKey );

        String pfops = fops + "|saveas/" + urlbase64;
        String upToken = auth.uploadToken(qiuNiuBucket, key, 3600, new StringMap().putNotEmpty("force","1").putNotEmpty("persistentOps", pfops));

        return  upToken;
        */
    //}

    /*
    private static void generateZoom(String qiuNiuBucket,String key,ImageInfoVo imageInfoVo){
        // 新建一个OperationManager对象
        OperationManager operater = new OperationManager(auth, cfg);
        // 设置要转码的空间和key，并且这个key在你空间中存在
        //String key
        // 设置转码操作参数
        ImageBucketEnum bucketEnum = ImageBucketEnum.getByValue(imageInfoVo.getBucket());
        if(bucketEnum.equals(ImageBucketEnum.VIDEO)||bucketEnum.getHeight()==null||bucketEnum.getWidth()==null){
            return ;
        }
        String fops = "imageView2/2/w/"+bucketEnum.getWidth()+"/h/"+bucketEnum.getHeight();
        int index=key.indexOf(".");
        String slimKey = key.substring(0,index)+"-zoom"+key.substring(index);
        String urlbase64 = UrlSafeBase64.encodeToString(qiuNiuBucket + ":" + slimKey );
        String pfops = fops + "|saveas/" + urlbase64;

        //可以对转码后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
        //设置pipeline参数
        StringMap params = new StringMap().putWhen("force", 1, true);
        try {
            //persistentId  z2.5b0bd78be3d00468087bc950
            String pfop = operater.pfop(qiuNiuBucket, key,pfops, params);
            //持久化的 执行进度
            OperationStatus operationStatus = operater.prefop(pfop);
            // http://p/uMAtcafSVjwXomg-y6DfpirkmPk=/FiR-CWCKlrWiQg561v0NjByFNXSh
            System.out.println("persistentId"+ pfop);
            System.out.println("执行状态"+ operationStatus.code);

            if( 0 == operationStatus.code && operationStatus.items.length > 0){
                System.out.println(operationStatus.items[0].key);
            }
        } catch (QiniuException e) {
            // 捕获异常信息
            Response r = e.response;
            // 请求失败时简单状态信息
            System.out.println(r.toString());
            try {
                // 响应的文本信息
                System.out.println(r.bodyString());
            } catch (QiniuException e1) {
                e1.printStackTrace();
            }
        }


    }
   */



}
